/*
 *  Copyright (C) 2011 glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.swing.commons;

import java.util.logging.Level;
import javax.swing.JComponent;
import javax.swing.text.JTextComponent;
import org.balisunrise.application.Application;
import org.balisunrise.application.ComponentManagers;
import org.balisunrise.common.Bindable;
import org.balisunrise.common.Binding;
import org.balisunrise.common.BindingGroup;
import org.balisunrise.common.ComponentManager;
import org.balisunrise.common.ConverterException;
import org.balisunrise.common.EntityFieldType;
import org.balisunrise.common.abstracts.AbstractFieldComponent;
import org.balisunrise.common.listeners.FieldInputListener;
import org.balisunrise.swing.components.FieldInputUtil;

/**
 *
 * @author glauco
 */
public class FieldInput<V extends JComponent>
        extends AbstractFieldComponent
        implements org.balisunrise.common.FieldInput<V>,Bindable{

    public static final String PROP_VALUE = "value";
    public static final String PROP_ENABLED = "enabled";
    public static final String PROP_BINDING = "binding";

    private V visualRepresentation;
    private boolean canEnable;
    private Object oldValue;
    private FieldInputUtil fieldInputUtil;
    private Binding binding;

    public FieldInput(V visualRepresentation, boolean canEnable) {
        this.visualRepresentation = visualRepresentation;
        this.canEnable = canEnable;
        
        fieldInputUtil = new FieldInputUtil(this);

        visualRepresentation.addAncestorListener(fieldInputUtil);
        visualRepresentation.addFocusListener(fieldInputUtil);
        if (visualRepresentation instanceof JTextComponent)
            ((JTextComponent)visualRepresentation)
                    .getDocument()
                    .addDocumentListener(fieldInputUtil);
    }

    public Binding getBinding() {
        return binding;
    }

    public void setBinding(Binding binding) {

        Binding old = this.binding;

        if (old != null)
            old.removeListener(fieldInputUtil);
        binding.addListener(fieldInputUtil);

        this.binding = binding;
        changeSupport.firePropertyChange(PROP_BINDING, old, binding);
    }

    @Override
    public ComponentManager<?, V> getComponentManager() {
        try{
            ComponentManagers cms = Application.get().getComponentManagers();
            ComponentManager<?,V> cm = cms.getComponentManager(fieldClass);
            return cm;
        }catch(Exception ex){
            Application.get().getLogger().log(Level.SEVERE,
                    "FieldInput não pode pegar um CamponentManager", ex);
        }
        return null;
    }

    @Override
    public Object getValue() {
        ComponentManager cm = getComponentManager();
        return cm.readValue(visualRepresentation);
    }

    @Override
    public void setValue(Object value) {
        try{
            ComponentManager cm = getComponentManager();
            cm.insertValue(visualRepresentation, value);
            changeSupport.firePropertyChange(PROP_VALUE, oldValue, value);
            oldValue = value;
        }catch(ConverterException ccex){
            System.out.println(ccex.getMessage());
        }
    }

    @Override
    public boolean requestFocus() {
        if(visualRepresentation.isEnabled()
                && visualRepresentation.isFocusable()){
            visualRepresentation.requestFocus();
            return true;
        }
        return false;
    }

    @Override
    public V getVisualRepresentation() {
        return visualRepresentation;
    }

    @Override
    public EntityFieldType getEntityFieldType() {
        return EntityFieldType.INPUT;
    }

    @Override
    public boolean setEnabled(boolean value) {
        if(canEnable){
            boolean old = visualRepresentation.isEnabled();
            visualRepresentation.setEnabled(value);
            changeSupport.firePropertyChange(PROP_ENABLED, old, value);
            return true;
        }
        return false;
    }

    @Override
    public void addFieldInputListener(FieldInputListener fl) {
        fieldInputUtil.getInputListeners().add(fl);
    }

    @Override
    public FieldInputListener[] getFieldInputListeners() {
        return fieldInputUtil.getInputListeners()
                .toArray(new FieldInputListener[]{});
    }

    @Override
    public boolean removeFieldInputListener(FieldInputListener fl) {
        return fieldInputUtil.getInputListeners().remove(fl);
    }

    @Override
    public void bindComponent(BindingGroup bindingGroup, Object source,
            String sourceProperty) {

        Binding b = getComponentManager().createBinding(
                bindingGroup,
                source,
                sourceProperty,
                getVisualRepresentation(),
                true,
                this);
        
        setBinding(b);
    }

}
